home *** CD-ROM | disk | FTP | other *** search
- ftype 'APPL'
- fsign 'TesT'
-
- incl "All Traps.PSM"
-
- ScreenRow equ $106
-
- a5Sec
- TheBlock ds.l 1
- a5End
-
-
- ;--------------------------------------------------------------
- ;--- 5 Sorts Demonstration
- ;---
- ;--- A. Initialize the System
- ;--- (Note! _Random #'s are not valid before _InitGraf!
- ;---
- ;--- B. Allocate a block of Memory and Fill with random #'s
- ;--- and
- ;--- C. Sort the block using;
- ;--- 1. Bubble Sort
- ;--- 2. SelectionSort
- ;--- 3. InsertionSort
- ;--- 4. ShellSort
- ;--- 5. QuickSort
- ;-------------------------------------------------------------
- ;--- These are the Rules
- ;--- 1. Each element in the block is a WORD in length
- ;--- 2. The number $FACE is placed at the end
- ;--- of the block as a marker (debugging)
- ;--- 3. N is the number of words in the block
- ;--- 4. The sort is by signed word
- ;--- 5. These subroutines were coded and tested for blocks
- ;--- of up to 500K. (Not recommended for bubble sort)
- ;--- Note that in some cases simply inverting the comparisons
- ;--- from BGT to BLT will reverse the order of the sort
-
-
- ; Procedure BubbleSort ( N:LongInt ; p:Pointer )
- ; Procedure SelectionSort ( N:LongInt ; p:Pointer )
- ; Procedure InsertionSort ( N:LongInt ; p:Pointer )
- ; Procedure ShellSort ( N:LongInt ; p:Pointer )
- ; Procedure QuickSort ( N:LongInt ; p:Pointer )
-
- ; You are welcome to use these sorts in any of your programs
- ; based on one of the following license programs;
-
- ; a. Pay me one Italian Lire for each number sorted.
- ; or
- ; b. Mention my name if you use QuickSort.
- ; or
- ; c. Go to church next sunday.
- ;
- ; ***Please consult your lawyer***
-
-
-
- OutOfSorts
- pea -4(a5)
- _InitGraf
- _InitFonts
- _InitWindows
- _InitMenus
- clr.l -(sp)
- _InitDialogs
- _TEInit
-
- ;
- move.l -4(a5),a0 a0 = ptr to QuickDraw globals
-
- move.w 12(a0),d7 Screen Height *
- muls ScreenRow,d7 Bytes/Line
- lsr.l #1,d7 /2 = Words on the Screen
-
-
- move.l $824,TheBlock
-
- ;******************************************************
- ; If you want to use a nonrelocatable block in memory
- ; you could do it this way
- ;N equ YourSize
- ; move.l #N,d7 You choose the size
- ; move.l d7,d0
- ; add.l d0,d0 Blocksize = N* 2 bytes/word
- ; addq.l #2,d0 + word marker #$FACE
- ; _NewPtr
- ; tst.w d0
- ; bmi Error
- ; move.l a0,TheBlock
- ;******************************************************
-
- ; in this program, d7 will hold #N
- ; If you want different sized blocks to be allocated and sorted
- ; just place your value into d7 here
-
-
- bsr FillBlock
-
- move.l d7,-(sp)
- move.l TheBlock,-(sp)
- bsr BubbleSort
-
- bsr FillBlock
-
- move.l d7,-(sp)
- move.l TheBlock,-(sp)
- bsr SelectionSort
-
- bsr FillBlock
-
- move.l d7,-(sp)
- move.l TheBlock,-(sp)
- bsr InsertionSort
-
- bsr FillBlock
-
- move.l d7,-(sp)
- move.l TheBlock,-(sp)
- bsr ShellSort
-
- bsr FillBlock
-
- move.l d7,-(sp)
- move.l TheBlock,-(sp)
- bsr QuickSort
-
- Rts
-
-
- ; The Bubble Sort algorithm is dedicated to STOP pipe tobacco
- ; (Alfred & Christian Peterson, Horsens, Danmark)
- ; because sometimes it seems as though it never will.
-
- ; Pass through block repeatedly, exchanging adjacent elements
- ; until exchanges = 0
-
- BubbleSort
- movem.l d3/d4/a2,-(A7)
- move.l 20(sp),d4
- sub.l #2,d4 D2 = Block counter
- bmi.s NoBubbles
- move.l 16(sp),a2
-
- DoBS move.l d4,d2
- moveq #0,d3 d3 = exchanges
- move.l a2,a0
- lea 2(a0),a1
-
- NextBubble
- cmpm.w (a0)+,(a1)+
- bge.s InOrder BLE Reverses sort order
-
- move.w (a0),d0
- move.w -2(a0),(a0) Swap the Numbers
- move.w d0,-2(a0)
- addq.l #1,d3 mark exchange
-
- InOrder subq.l #1,d2
- bpl NextBubble
- tst.l d3 Exchanges = 0?
- bne.s DoBS >No, Start from the beginning
- NoBubbles movem.l (sp)+,d3/d4/a2 >Yes, all done
- move.l (sp)+,a0
- addq.w #8,sp
- jmp (a0)
-
-
- ; Selection Sort Algorithm
- ;
-
- SelectionSort
- move.l a2,-(A7)
- move.l 12(sp),d2 D2 = Block counter
- subq.l #1,d2
- ble.s SFinish
- move.l 8(sp),a2 A2 = Unsorted Base
- bra.s .first
-
- SFinish movem.l (sp)+,a2 >Yes, all done
- move.l (sp)+,a0
- addq.w #8,sp
- jmp (a0)
-
-
- NxtSel subq.l #1,d2
- bmi SFinish
- move.w (A2),D3
- move.w (a1),(A2)+ A2 is Updated each pass
- move.w d3,(a1) After each # is added
-
- .first move.l d2,d1
- move.w (A2),d0
- move.l A2,a1 A1 = Address of the smallest #
- lea 2(A2),a0 A0 = next # to compare to (a1)
-
- D0Cmp subq.l #1,d1
- bmi NxtSel
- cmp.w (a0)+,d0
- blt D0Cmp
- move.l a0,a1
- move.w -(a1),d0
- bra D0Cmp
-
-
- ; Note that Insertion Sort is the Quickest of all for a
- ; sorted block (Quicksort is the worst!).
-
- InsertionSort
- link a6,#0
- movem.l d3/a2/a3,-(sp)
- move.L 8(A6),A3
- move.L 12(A6),D2
- moveq #0,d1
- moveq #0,d0 D0 = CMP Register
- move.l a3,A2 a3 = Base of Block
- moveq #-1,d3
- lea 2(a3),a0
- subq.l #1,d2
-
- NextInsert
- addq.l #1,d3 d3 = Insert Block Size
- cmp.l d3,d2
- ble.s Ifinished
- move.l a0,A2
- move.w (a0)+,d0 New Entry> D0
-
- NextPos
- move.w -(A2),d1
- cmp.w d0,d1
- bge.s Trade
-
- move.w d0,2(A2) Drop
- bra.s NextInsert
-
- Trade move.w d1,2(A2) Swap
- move.w d0,(A2)
- cmp.l a3,A2
- bne.s NextPos
- bra.s NextInsert
-
- IFinished movem.l (sp)+,d3/a2/a3
- unlk a6
- move.l (sp)+,a0
- addq.w #8,sp
- jmp (a0)
-
- ;--------------------------------------------------------
- ;--- This is ShellSort stolen from MacNosey
- ;--- as demanded by it's author, Steve Jasik.
- ;--- I modified it somewhat to handle bigger blocks.
- ;
- ; Shell Sort Algorithm
- ; N = 5000 Time= 0.5 Seconds
- ; = 10000 0.9
- ; = 20000 1.5
-
- ShellSort LINK A6,#0
- MOVEM.L D3-D7/A2-A3,-(SP)
- MOVEA.L 8(A6),A2 ; tbl addr
- MOVE.L 12(A6),D7 ; n
- CMPI.L #1,D7
- BLE.S luj_6 ; if n <= 1
- LEA HTable,A1
- moveq #0,d0
- moveq #0,d2
- luj_1 ADDQ.l #4,D0 ; k := k + 1
- MOVE.l 0(A1,D0.l),D3
- CMP.l D7,D3 ; if gap <= n
- BLT.S luj_1
- LSL.L #1,D7
- SUBQ.L #2,D7 ; d7 = 8*n-8
- luj_2 SUBQ.l #4,D0 ; k := k - 1
- MOVE.l 0(A1,D0.l),D3
- LSL.l #1,D3
- MOVE.l D3,D1
- luj_3 MOVE.w (A2,D1.l),D4
- MOVE.l D1,D2
- SUB.l D3,D2
- MOVEA.L A2,A3
- ADDA.l D3,A3
- luj_4 TST.l D2
- BLT.S luj_5
- MOVE.w 0(A2,D2.l),D6
- CMP.w D4,D6
- BLE.S luj_5
- MOVE.w D6,0(A3,D2.l)
- SUB.l D3,D2
- BRA.S luj_4
- luj_5 MOVE.w D4,0(A3,D2.l)
- ADDQ.l #2,D1
- CMP.l D7,D1
- BLE.S luj_3
- TST.l D0
- BNE.S luj_2
- luj_6 MOVEM.L (SP)+,D3-D7/A2-A3
- UNLK A6
- MOVE.L (SP)+,A0
- ADDQ #8,SP
- JMP (A0)
-
- ; Next = (Prev*3)+1
- HTable DC.l 1,4,$D,$28,$79,$16C,$445,$CD0
- dc.l $2671,$7354,$159FD,$40DF8,$C29CE9
-
-
- ; QuickSort, invented by C. Hoare in 1960
- ; Written for the MC68K by John Shepardson
- ; This method is so quick that it sorts the numbers
- ; faster than they are generated in FillBlock!
-
- QuickSort lea 8(a7),a0
- movem.l d3-d7/a2-a4,-(sp)
- move.l (a0),d0 N*2 in d0
- asl.l #1,d0
- ble QSRtn
- move.l d0,-(sp)
- move.l -(a0),-(sp)
- pea QSRtn
- moveq #2,d4 D4 = Constant #2
-
- ; we could just enter here and skip the above stack bashing
- ; except that registers d3-d7/a2-a4 would not be restored
- ; and N would have to be multiplied * 2 before calling
-
- QSJob move.l (sp)+,a3 a3 -> Return
- move.l (sp)+,a4 a4 -> Block
- move.l (sp)+,d7 D7 = Block Size
-
- ; PV = Partition Value
- QSReg lea (a4,d7.l),a1 A1 -> End
- move.w -(a1),d0 Last element = PV
- move.l a4,a0 A0 -> Front
- move.l d7,d2 D2 = Counter for A0
- subq.l #2,d2
- move.l d2,d3 D3 = Counter for A1
-
- ; Search from Start to end for an element >= d0
-
- NextUp cmp.w (a0)+,d0 Undwinding loops
- ble.s NextDwn Speeds up execution
- subq.l #2,d2
- bmi.s NextDwn
- cmp.w (a0)+,d0
- ble.s NextDwn
- subq.l #2,d2
- bmi.s NextDwn
- cmp.w (a0)+,d0
- ble.s NextDwn
- subq.l #2,d2
- bmi.s NextDwn
- cmp.w (a0)+,d0
- ble.s NextDwn
- subq.l #2,d2
- bmi.s NextDwn
- cmp.w (a0)+,d0
- ble.s NextDwn
- subq.l #2,d2
- bpl.s NextUp
-
- ;------------------------------------------------
-
- ; Search from End to Start for a #<= d0
- NextDwn cmp.w -(A1),d0
- bge.s ExchQS
- subq.l #2,d3
- bmi.s ExchQS
- cmp.w -(A1),d0
- bge.s ExchQS
- subq.l #2,d3
- bmi.s ExchQS
- cmp.w -(A1),d0
- bge.s ExchQS
- subq.l #2,d3
- bmi.s ExchQS
- cmp.w -(A1),d0
- bge.s ExchQS
- subq.l #2,d3
- bmi.s ExchQS
- cmp.w -(A1),d0
- bge.s ExchQS
- subq.l #2,d3
- bpl.s NextDwn
-
- ExchQS cmp.l a0,a1 Have they Crossed?
- blt.s LastSwap
-
- subq.l #2,d3 No, exchange
- subq.l #2,d2 & continue search
- move.w -2(A0),d1
- move.w (A1),-2(A0)
- move.w d1,(A1)
- bra NextUp
-
- LastSwap move.w -2(a0),-2(a4,d7.l) Yes, last exchange
- move.w d0,-2(a0) places the PV into
- addq.l #2,d3 it's final position
-
- cmp.l d4,d3 if elements = 1 or 0, Don't sort
- bgt.s QS2jobs
- sub.l D3,d7
- move.l a0,a4
- cmp.l d4,d7 1 job left in registers
- bgt.s QSReg
- jmp (a3) 0 jobs left in registers, exit
-
- QS2jobs sub.l D3,d7
- cmp.l d4,d7
- ble.s .npush
- move.l d7,-(sp)
- move.l a0,-(sp) To recurse really is Divine!
- move.l a3,-(sp)
- Lea QSJob,a3 1 job placed on stack
-
- .npush subq.l #4,d3
- move.l d3,d7 & 1 job left in registers
- cmp.l d4,d7
- bgt.s QSReg
-
- QDone jmp (a3)
-
- QSRtn movem.l (sp)+,d3-d7/a2-a4
- move.l (sp)+,a0
- addq.l #8,sp
- jmp (a0)
-
-
- Error dc.w $a9ff No Block to allocate
- _ExittoShell so lets go home
-
-
- FillBlock move.l d7,d3 with Random Numbers
- move.l TheBlock,a2
- NxtRand clr.w -(sp)
- _Random
- move.w (sp)+,(a2)+
- subq.l #1,d3
- bne NxtRand
- move.w #$FACE,(a2)+ Place marker at end
- rts
-
-
- end